package ren.kane.phoenix.util.reflect;

import java.lang.reflect.Constructor;

/**
 * @author renrk(1275) on 2019-08-13 4:52 PM
 **/
public class ConstructorTest {

    private static void testGetDeclaredConstructor() {
        try {
            Class<?> clazz = Class.forName("ren.kane.phoenix.util.reflect.Person2");
            Constructor constructor1 = clazz.getDeclaredConstructor();
            Constructor constructor2 = clazz.getDeclaredConstructor(String.class);
            Constructor constructor3 = clazz.getDeclaredConstructor(String.class, int.class, Gender.class);
            // 因为Person中Person()是private的，所以这里要设置为可访问
            constructor1.setAccessible(true);
            Object p1 = constructor1.newInstance();
            Object p2 = constructor2.newInstance("Tom");
            Object p3 = constructor3.newInstance("Jack", 30, Gender.MALE);

            System.out.printf("%-30s: p1=%s, p2=%s, p3=%s\n", "getConstructor()", p1, p2, p3);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void testGetConstructor() {
        try {
            Class<?> clazz = Class.forName("ren.kane.phoenix.util.reflect.Person2");
            Constructor constructor = clazz.getConstructor(String.class, int.class, Gender.class);
            Object p = constructor.newInstance("Jack", 30, Gender.MALE);
            System.out.printf("%-30s: p=%s\n", "getConstructor()", p);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void testGetEnclosingConstructor() {
        try {
            Class<?> clazz = Class.forName("ren.kane.phoenix.util.reflect.Person2");
            Constructor constructor = clazz.getDeclaredConstructor(String.class, int.class);
            Object obj = constructor.newInstance("Amy", 18);
            System.out.printf("%-30s: obj=%s\n", "getEnclosingConstructor()", obj);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        testGetDeclaredConstructor();
        testGetConstructor();
        testGetEnclosingConstructor();
    }
}

enum Gender {
    MALE, FEMALE
}

class Person2 {
    private String name;
    private int age;
    private Gender gender;

    private Person2() {
        this.name = "unknown";
        this.age = 0;
        this.gender = Gender.FEMALE;
        System.out.println("call--\"private Person2()\"");
    }

    protected Person2(String name) {
        this.name = name;
        this.age = 0;
        this.gender = Gender.FEMALE;
        System.out.println("call--\"protected Person2(String name)\"");
    }

    public Person2(String name, int age, Gender gender) {
        this.name = name;
        this.age = age;
        this.gender = gender;
        System.out.println("call--\"public Person2(String name, int age, Gender gender)\"");
    }

    public Person2(String name, int age) {
        this.name = name;
        this.age = age;
        this.gender = Gender.FEMALE;
        class InnerA {
        }
        Class clazz = InnerA.class;
        Constructor constructor = clazz.getEnclosingConstructor();
        System.out.println("call--\"public Person2(String name, int age)\" constructor=" + constructor);
    }

    @Override
    public String toString() {
        return "(" + name + ", " + age + ", " + gender + ")";
    }
}